package com.atguigu.gulimall.product.service.impl;

import com.atguigu.common.constant.ProductConstant;
import com.atguigu.gulimall.product.dao.AttrAttrgroupRelationDao;
import com.atguigu.gulimall.product.dao.AttrGroupDao;
import com.atguigu.gulimall.product.dao.CategoryDao;
import com.atguigu.gulimall.product.entity.AttrAttrgroupRelationEntity;
import com.atguigu.gulimall.product.entity.AttrGroupEntity;
import com.atguigu.gulimall.product.entity.CategoryEntity;
import com.atguigu.gulimall.product.service.CategoryService;
import com.atguigu.gulimall.product.vo.AttrGroupRelationVo;
import com.atguigu.gulimall.product.vo.AttrRespVo;
import com.atguigu.gulimall.product.vo.AttrVo;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.atguigu.common.utils.PageUtils;
import com.atguigu.common.utils.Query;

import com.atguigu.gulimall.product.dao.AttrDao;
import com.atguigu.gulimall.product.entity.AttrEntity;
import com.atguigu.gulimall.product.service.AttrService;
import org.springframework.transaction.annotation.Transactional;
/**
 * 商品属性
 */
@Service("attrService")
public class AttrServiceImpl extends ServiceImpl<AttrDao, AttrEntity> implements AttrService {
    @Autowired AttrAttrgroupRelationDao attrAttrgroupRelationDao;
    @Autowired CategoryDao categoryDao;
    @Autowired AttrGroupDao attrGroupDao;
    @Autowired CategoryService categoryService;

    /**
     * 查询属性分组下所有的关联的基本属性
     */
    @Override
    public List<AttrEntity> getRelationAttr(Long attrgroupId) {
        //1、根据 属性分组id 查询 属性分组关联表 下的 所有属性
        List<AttrAttrgroupRelationEntity> relationEntities = attrAttrgroupRelationDao.selectList(
                new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_group_id", attrgroupId));

        //2、再获取这些属性里面的 属性id
        List<Long> attrIds = relationEntities.stream().map((entity) -> {
            return entity.getAttrId();
        }).collect(Collectors.toList());

        if(attrIds == null || attrIds.size() == 0){
            return null;
        }

        //3、根据 属性id 批量查询属性，再返回
        List<AttrEntity> attrEntities = this.baseMapper.selectBatchIds(attrIds);
        return attrEntities;
    }

    /**
     * 获取本属性分组下没有关联的其他属性
     */
    @Override
    public PageUtils getNoRelationAttr(Map<String, Object> params, Long attrgroupId) {
        //1、当前分组只能关联自己所属分类里面的所有属性 【比如 "主体" 分组只能关联 "手机" 分类下的所有属性】
        //获取本分组的分类id
        AttrGroupEntity attrGroupEntity = attrGroupDao.selectById(attrgroupId);    //根据分组id 查询 分组信息
        Long catelogId = attrGroupEntity.getCatelogId();    //再从分组信息里面获取 分类id

        //2、同一个分类下，当前分组只能关联别的分组没有关联的属性 【比如同一个 "手机" 分类下，当前 "主体" 分组只能关联 "基本信息" 分组没有关联的属性】
        //2.1 根据 分类id 获取当前分类下的所有 分组 信息 【比如 "手机" 分类下的所有分组，包括 "主体" 分组和 "基本信息" 分组】
        List<AttrGroupEntity> attrGroupEntities = attrGroupDao.selectList(
                new QueryWrapper<AttrGroupEntity>().eq("catelog_id", catelogId));

        //从这些分组信息里面获取 属性分组id
        List<Long> attrGroupIds = attrGroupEntities.stream().map(attrGroupEntity1 -> {
            return attrGroupEntity1.getAttrGroupId();
        }).collect(Collectors.toList());

        //2.2 根据 属性分组id 查询这些分组关联的属性 【比如 "主体" 分组和 "基本信息" 分组都关联了哪些属性】
        List<AttrAttrgroupRelationEntity> relationEntities = attrAttrgroupRelationDao.selectList(
                new QueryWrapper<AttrAttrgroupRelationEntity>().in("attr_group_id", attrGroupIds));

        //从属性分组关联表 里面获取 属性id 【比如 "主体" 分组和  "基本信息" 分组他们关联的属性的 id】
        List<Long> attrIds = relationEntities.stream().map((relationEntity) -> {
            return relationEntity.getAttrId();
        }).collect(Collectors.toList());

        //3、构建最终的查询条件
        QueryWrapper<AttrEntity> wrapper = new QueryWrapper<AttrEntity>()
                .eq("catelog_id", catelogId)    //条件一：只查当前分类下的
                .eq("attr_type", ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode());    //条件二：只查基本属性

        //2.3 从当前分组的所有属性中移除这些属性 【比如从当前 "主体" 分组中移除 "基本信息" 分组已经关联了的属性，以及自己已经关联过的属性】
        if (attrIds != null && attrIds.size() > 0){
            wrapper.notIn("attr_id", attrIds);    //排除掉 attrIds (别的分组和自己分组已经关联过的属性)
        }

        //条件三：模糊查询或精确查询
        String key = (String) params.get("key");
        if (!StringUtils.isEmpty(key)){
            wrapper.and((w) -> {
                w.eq("attr_id", key).or().like("attr_name", key);
            });}

        //4、最终的分页查询
        IPage<AttrEntity> page = this.page(new Query<AttrEntity>().getPage(params), wrapper);
        return new PageUtils(page);
    }


    /**
     * 属性修改回显功能
     */
    @Override
    @Cacheable(value = "attr", key = "'attrinfo:' + #root.args[0]")    //#root.args[0]：表示传参的    第一个参数
    public AttrRespVo getAttrInfo(Long attrId) {
        AttrRespVo respVo = new AttrRespVo();
        AttrEntity attrEntity = this.getById(attrId);
        BeanUtils.copyProperties(attrEntity, respVo);

        //如果是基本属性(规格参数)，才保存属性分组关联表 的 分组信息
        if(attrEntity.getAttrType() == ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode()){
            //1、设置分组信息
            AttrAttrgroupRelationEntity attrgroupRelation = attrAttrgroupRelationDao.selectOne(
                    new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", attrId));
            if (attrgroupRelation != null){
                respVo.setAttrGroupId(attrgroupRelation.getAttrGroupId());    //设置属性分组id
                AttrGroupEntity attrGroupEntity = attrGroupDao.selectById(attrgroupRelation.getAttrId());

                if (attrGroupEntity != null){
                    respVo.setGroupName(attrGroupEntity.getAttrGroupName());    //设置属性分组名称
                }
            }
        }

        //2、设置分类信息
        Long catelogId = attrEntity.getCatelogId();
        Long[] catelogPath = categoryService.findCatelogPath(catelogId);    //调用《根据分类id查询分类的完整路径》方法
        respVo.setCatelogPath(catelogPath);    //设置分类的完整路径

        CategoryEntity categoryEntity = categoryDao.selectById(catelogId);
        if (categoryEntity != null){
            respVo.setCatelogName(categoryEntity.getName());    //设置分类名称
        }
        return respVo;
    }

    /**
     * 在指定的属性集合中，找出要检索的属性的id
     */
    @Override
    public List<Long> selectSearchAttrIds(List<Long> attrIds) {
        return baseMapper.selectSearchAttrIds(attrIds);
    }

    /**
     * 保存规格参数(基本属性)
     */
    @Override
    @Transactional    //开启事务
    public void saveAttr(AttrVo attr) {
        //1、保存基本数据
        AttrEntity attrEntity = new AttrEntity();

        BeanUtils.copyProperties(attr, attrEntity);    //attr 属性拷贝到 attrEntity，前提是他们俩的属性名一样的
        this.save(attrEntity);

        //如果是基本属性(规格参数)，才保存属性分组关联表
        if(attr.getAttrType() == ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode() && attr.getAttrGroupId() != null){
            //2、保存关联关系
            AttrAttrgroupRelationEntity relationEntity = new AttrAttrgroupRelationEntity();
            relationEntity.setAttrGroupId(attr.getAttrGroupId());
            relationEntity.setAttrId(attrEntity.getAttrId());
            attrAttrgroupRelationDao.insert(relationEntity);
        }}



    /**
     * 删除属性分组的关联关系 (属性与分组的关系)
     */
    @Override
    public void deleteRelation(AttrGroupRelationVo[] vos) {
        //1、把vos数组 转为 list集合
        List<AttrGroupRelationVo> relationVos = Arrays.asList(vos);
        List<AttrAttrgroupRelationEntity> entities = relationVos.stream().map((relationVo) -> {

            AttrAttrgroupRelationEntity relationEntity = new AttrAttrgroupRelationEntity();
            BeanUtils.copyProperties(relationVo, relationEntity);    //属性拷贝

            return relationEntity;
        }).collect(Collectors.toList());
        //2、根据 属性Id 和 分组Id 批量删除关联关系
        attrAttrgroupRelationDao.deleteBatchRelation(entities);
    }

    /**
     * 查询 规格参数(基本属性) 或 销售属性
     */
    @Override
    public PageUtils queryBaseAttrPage(Map<String, Object> params, Long catelogId, String type) {
        //1、查询基本数据
        QueryWrapper<AttrEntity> queryWrapper = new QueryWrapper<AttrEntity>().eq("attr_type",
                "base".equalsIgnoreCase(type) ? ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode()
                        : ProductConstant.AttrEnum.ATTR_TYPE_SALE.getCode());    //属性类型[0-销售属性，1-基本属性]

        if (catelogId != 0){
            queryWrapper.eq("catelog_id", catelogId);
        }

        String key = (String) params.get("key");
        if (!StringUtils.isEmpty(key)){
            queryWrapper.and((wrapper) -> {
                wrapper.eq("attr_id", key).or().like("attr_name", key);
            });
        }

        IPage<AttrEntity> page = this.page(new Query<AttrEntity>().getPage(params), queryWrapper);

        //2、查询另外的数据，比如 catelogName(分类名字) 和 groupName(分组名字)
        PageUtils pageUtils = new PageUtils(page);    //封装分页数据

        //查出新增的属性
        List<AttrEntity> records = page.getRecords();
        List<AttrRespVo> respVos = records.stream().map((attrEntity) -> {
            AttrRespVo attrRespVo = new AttrRespVo();
            BeanUtils.copyProperties(attrEntity, attrRespVo);

            //查询分类
            CategoryEntity categoryEntity = categoryDao.selectOne(
                    new QueryWrapper<CategoryEntity>().eq("cat_id", attrEntity.getCatelogId()));
            if (categoryEntity != null) {
                attrRespVo.setCatelogName(categoryEntity.getName());    //设置分类名称
            }

            //如果是基本属性(规格参数)，才保存属性分组关联表 的 分组信息
            if("base".equalsIgnoreCase(type)){
                //查询属性分组关联关系表
                AttrAttrgroupRelationEntity attrgroupRelationEntity = attrAttrgroupRelationDao.selectOne(
                        new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", attrEntity.getAttrId()));
                if (attrgroupRelationEntity != null && attrgroupRelationEntity.getAttrGroupId() != null) {
                    //查询属性分组
                    AttrGroupEntity attrGroupEntity = attrGroupDao.selectOne(
                            new QueryWrapper<AttrGroupEntity>().eq("attr_group_id", attrgroupRelationEntity.getAttrGroupId()));
                    attrRespVo.setGroupName(attrGroupEntity.getAttrGroupName());    //设置分组名称
                }}

            return attrRespVo;
        }).collect(Collectors.toList());
        pageUtils.setList(respVos);    //把新的数据传送过去
        return pageUtils;
    }

    /**
     * 修改属性
     */
    @Override
    @Transactional    //开启事务
    public void updateAttr(AttrVo attr) {
        //1、修改基本信息
        AttrEntity attrEntity = new AttrEntity();
        BeanUtils.copyProperties(attr, attrEntity);
        this.updateById(attrEntity);

        //如果是基本属性(规格参数)，才保存属性分组关联表 的 分组信息
        if(attrEntity.getAttrType() == ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode()){
            //2、修改 属性分组关联关系
            AttrAttrgroupRelationEntity relationEntity = new AttrAttrgroupRelationEntity();
            relationEntity.setAttrGroupId(attr.getAttrGroupId());
            relationEntity.setAttrId(attr.getAttrId());

            //3、判断是新增还是修改
            Integer count = attrAttrgroupRelationDao.selectCount(
                    new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", attr.getAttrId()));
            if (count > 0){    //如果 属性分组关联关系表 有数据，就是修改
                attrAttrgroupRelationDao.update(
                        relationEntity, new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", attr.getAttrId()));
            }else{    //没有数据，就是新增
                attrAttrgroupRelationDao.insert(relationEntity);
            }}}

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<AttrEntity> page = this.page(new Query<AttrEntity>().getPage(params), new QueryWrapper<AttrEntity>());
        return new PageUtils(page);
    }
}